home *** CD-ROM | disk | FTP | other *** search
/ Disc to the Future 2 / Disc to the Future Part II Programmer's Reference (Wayzata Technology)(6013)(1992).bin / MAC / THINKC / 4_0 / TIFF_WIN / TIFF.C < prev    next >
Text File  |  1990-04-25  |  13KB  |  342 lines

  1. /*
  2.         Experiments in reading a TIFF file
  3.         
  4. */
  5. /* In this routine I prompt the user for the name of a TIFF file
  6.     If the user gives me a valid name, I will treat the file as a 
  7.     TIFF file and interpret the records accordingly.  I am trusting 
  8.     the user to have given me the name of a TIFF file and not the 
  9.     name of some other type of file. Once I have the name of the file
  10.     I read in the TIFF data and then construct an off screen CGrafPort.
  11.     the CGrafPort is very easy to create on a Macintosh and it solves 
  12.     many problems dealing with scrolling and color.
  13.     
  14.     The fun part of this code is where I create the Color Table and use 
  15.     that to create a Color Palette. 
  16.     You should read up on the palette manager in InsideMac Vol 5 and 
  17.     then play around with the code to see the different effects that 
  18.     you can accomplish.
  19. */
  20.  
  21.  
  22. #include "my color.h"
  23. #include "tiff.h"
  24. #include <StdFilePkg.h>
  25. #include <FileMgr.h>
  26. #define DOTS_PER_INCH_72    0x00480000
  27. CGrafPtr read_tiff_file(new_window)
  28. CWindowPtr    new_window;
  29. {
  30. OSErr            io_errors;
  31. char            *my_prompt;
  32. Point            cornor_of_dialog_box;
  33. register short    even_constant, i;
  34. short            file_ref_num, number_of_file_types, nBits;
  35. long            header_size;
  36. long            value, pixels_per_line, nLines, picture_size;
  37. char            *PicbaseAddr;
  38. SFReply            the_responce_to_me;
  39. SFTypeList        my_type;
  40. PixMapHandle    tiff_map;
  41. short            max_value, min_value, photo_type, response_curve, response_unit, number_of_pm_entries;
  42. CTabHandle        color_table;
  43. PaletteHandle    picture_palette, window_palette;
  44. CGrafPtr        the_picture;
  45. long            next_IFD_offset, offset_to_the_image;
  46. short            program_resource, TIFF_res_file, number_of_clut;
  47. CTabHandle        the_clut_to_use;
  48. RGBColor        rgb_black, rgb_white;
  49. Rect            tempRect;
  50.  
  51.     color_table    = 0L;    /* initialize the important Ptrs/Handles to zero */
  52.     tiff_map    = 0L;
  53.     the_picture    = 0L;
  54.     PicbaseAddr    = 0L;
  55.  
  56.  
  57.     rgb_black.red = rgb_black.green = rgb_black.blue = 0x0000;
  58.     rgb_white.red = rgb_white.green = rgb_white.blue = 0xFFFF;
  59.  
  60.     tiff_map = (PixMapHandle)NewHandle(sizeof(PixMap));    /* get RAM for the PixMap */
  61.     if(!tiff_map) return (CGrafPtr)0L;                    /* if I failed, return a NULL pointer */
  62.  
  63.     cornor_of_dialog_box.h = 50;        /* draw the SFGetFile dialog at this point */
  64.     cornor_of_dialog_box.v = 50;
  65.     my_prompt = "\pWhere is TIFF?";
  66.     
  67.     number_of_file_types = 1;
  68.     my_type[0] = 'TIFF';
  69.  
  70.     SFGetFile(cornor_of_dialog_box, my_prompt, (ProcPtr)0, number_of_file_types, my_type,
  71.             (ProcPtr)0, &the_responce_to_me);
  72.  
  73.     if(!the_responce_to_me.good) return    0l;    /* If the user didn't want to open a file with this window, return a NULL pointer */
  74.     SetWTitle(new_window, the_responce_to_me.fName);
  75.     io_errors = FSOpen(the_responce_to_me.fName, the_responce_to_me.vRefNum, 
  76.                         &file_ref_num);                /* Open the chosen TIFF file */
  77.     
  78.     header_size = (long)sizeof(tiff_header);
  79.     io_errors = FSRead(file_ref_num, &header_size, &tiff_header);    /* read the TIFF header */
  80.  
  81.     io_errors = SetFPos(file_ref_num, fsFromStart, tiff_header.first_IFD);    /* read in the first IFD */
  82.     header_size = (long)sizeof(number_of_directories);
  83.     io_errors = FSRead(file_ref_num, &header_size, &number_of_directories);    /* read how many image directories there are in the TIFF file */
  84.  
  85.     header_size = (long)sizeof(tiff_directory);
  86.  
  87.     ifd = (struct directory_entry *)NewPtr((long)sizeof(tiff_directory));    /* get some RAM for the IFD */
  88.  
  89.     if(tiff_header.first_IFD > 0)
  90.     min_value = 0;                    /* the default minimum value */
  91.     max_value = 256;                /* the default maximum value */
  92.     photo_type = 0;                    /* the default photo metric interpretation */
  93.  
  94.         for(i=0; i < number_of_directories; i++)
  95.             {
  96.                 header_size = (long)sizeof(tiff_directory);    /* the size of a IFD record */
  97.                 io_errors = FSRead(file_ref_num, &header_size, ifd);    /* read the IFD */
  98.                 if(ifd->type == SHORT)
  99.                     value = (long)ifd->tag_value.short_value;
  100.                 else if(ifd->type == LONG)
  101.                     value = ifd->tag_value.long_value;
  102.                 
  103.                 switch(ifd->tag)        /* decipher the TAG */
  104.                 {
  105.                     case SubFileType:
  106.                         break;
  107.                         
  108.                     case ImageWidth:
  109.                         pixels_per_line = value;
  110.                         break;
  111.                         
  112.                     case ImageLength:
  113.                         nLines = value;
  114.                         break;
  115.                     
  116.                     case BitsPerSample:
  117.                         nBits = value;
  118.                         min_value = 0;
  119.                         max_value = 256;
  120.                         break;
  121.                         
  122.                     case MaxSampleValue:
  123.                         max_value = value;
  124.                         break;
  125.                         
  126.                     case MinSampleValue:
  127.                         min_value = value;
  128.                         break;
  129.                         
  130.                     case PhotometricInterpretation:
  131.                         photo_type = value;
  132.                         break;
  133.                         
  134.                     case GrayResponseUnit:
  135.                         response_unit = value;
  136.                         break;
  137.                         
  138.                     case GrayResponseCurve:
  139.                         response_curve = value;
  140.                         break;
  141.                         
  142.                     case StripOffsets:
  143.                         offset_to_the_image = value;
  144.                 }
  145.             }
  146.  
  147.         header_size = (long)sizeof(long);
  148.         io_errors = FSRead(file_ref_num, &header_size, &next_IFD_offset);    /* read how many image directories there are in the TIFF file */
  149.  
  150.         the_picture = (CGrafPtr)NewPtr(sizeof(CGrafPort));    /* Get RAM for the color graf port */
  151.         if(!the_picture)
  152.         {
  153.             SysBeep(10); 
  154.             if(color_table) DisposHandle(color_table);
  155.             if(tiff_map)     DisposHandle(tiff_map);
  156.             if(the_picture) DisposPtr(the_picture);
  157.             if(PicbaseAddr) DisposPtr(PicbaseAddr);
  158.             return (CGrafPtr)0L;
  159.         }
  160.     
  161. /* now I'll go ahead and open the file and read it in */
  162.  
  163.         picture_size = pixels_per_line * nLines;
  164.         PicbaseAddr = NewPtr(picture_size);        /* get enough RAM to hold The TIFF picture */
  165.         if(!PicbaseAddr) /* If I don't suceed then quit */
  166.         { 
  167.             SysBeep(10); 
  168.             DisposHandle(tiff_map);
  169.             DisposPtr(the_picture);
  170.             return (CGrafPtr)0L;
  171.         }
  172.         
  173.     /* tiff_map is a CGrafPort, here is were many parameters are set 
  174.         based on what I read in from the TIFF file */
  175.         (**tiff_map).baseAddr = PicbaseAddr;
  176.         (**tiff_map).pixelSize = nBits;
  177.         (**tiff_map).rowBytes = pixels_per_line | 0x8000;
  178.         (**tiff_map).bounds.top = 0;
  179.         (**tiff_map).bounds.left = 0;
  180.         (**tiff_map).bounds.bottom = nLines;
  181.         (**tiff_map).bounds.right = pixels_per_line;
  182.         (**tiff_map).pixelType = 0;
  183.         (**tiff_map).hRes = DOTS_PER_INCH_72;
  184.         (**tiff_map).vRes = DOTS_PER_INCH_72;
  185.         (**tiff_map).cmpCount = 1;
  186.         (**tiff_map).cmpSize = (**tiff_map).pixelSize;
  187.         (**tiff_map).planeBytes = 0;
  188.         (**tiff_map).pmReserved = 0;
  189.  
  190. /*
  191.     ============================== Creating the clut ================================
  192. */
  193. /* Some TIFF files created on Macintosh computers will have a clut resource, lets see if this TIFF file does! */
  194.  
  195.     program_resource = CurResFile();    /* lets remember which resfile is being used before we change it!! */
  196.         
  197.     TIFF_res_file = OpenRFPerm(the_responce_to_me.fName, the_responce_to_me.vRefNum, fsRdPerm);
  198.     if((number_of_clut = Count1Resources('clut')) == 0)
  199.     {
  200. /* ******************************************************************************* */
  201. /* If I fell through to here then there isn't a clut Resource!  
  202.  
  203.     Create the Color Table from the TIFF parameters
  204. */
  205.     UseResFile(program_resource);    /* reset the resource back to the program */
  206.     color_table = (CTabHandle)NewHandle((Size)(sizeof(ColorTable) + 
  207.                     (sizeof(ColorSpec) * (max_value - min_value))));    /* get RAM for the color TABLE */
  208.     if(!color_table) 
  209.     { 
  210.             SysBeep(10); 
  211.             if(color_table) DisposHandle(color_table);
  212.             if(tiff_map)     DisposHandle(tiff_map);
  213.             if(the_picture) DisposPtr(the_picture);
  214.             if(PicbaseAddr) DisposPtr(PicbaseAddr);
  215.             return (CGrafPtr)0L;
  216.     }
  217.     (**color_table).ctSeed = GetCTSeed();
  218.     (**color_table).ctFlags = 0;
  219.     (**color_table).ctSize = (short)(max_value - min_value);
  220.     number_of_pm_entries = (short)(max_value - min_value);
  221. /* Now I'm going to create a color Table with Gray Scale values,  
  222.     most likely there will be 256 entries, but the number of entries 
  223.     actually depends of the max_value I read in from the TIFF file */
  224.     
  225.     even_constant =  65535 / (max_value - min_value);    /* I will evenly space the grayscale values through the color table */
  226.     if(photo_type == 1)    /* photo type is a value I read from the TIFF 
  227.                             file. If its value is 1, then the gray 
  228.                             colors are ascending, and the picture looks 
  229.                             like a normal black and white photo. If 
  230.                             photo_type was 0 (Zero) then the gray scale 
  231.                             values are decending, and the picture looks 
  232.                             like a black and white negative! */ 
  233.         for(i= 0; i < max_value; i++)
  234.         {                /* change these values to get really interesting 
  235.                             effects, like multiply red by 2 and green by 
  236.                             4 and see what happens */
  237.             (**color_table).ctTable[i].value =        i;
  238.             (**color_table).ctTable[i].rgb.red =    (i * even_constant);
  239.             (**color_table).ctTable[i].rgb.green =    (i * even_constant);
  240.             (**color_table).ctTable[i].rgb.blue =    (i * even_constant);
  241.         }
  242.     else if(photo_type == 0)
  243.         for(i= max_value; i > 0; i--)
  244.         {
  245.             (**color_table).ctTable[i].value =        max_value - i;
  246.             (**color_table).ctTable[i].rgb.red =    (i * even_constant);
  247.             (**color_table).ctTable[i].rgb.green =    (i * even_constant);
  248.             (**color_table).ctTable[i].rgb.blue =    (i * even_constant);
  249.         }
  250.     }
  251. /* ******************************************************************************** */
  252.     else    /* A resource fork exists with a clut! Lets read it in! */
  253.     {        /* to experiment, try using ResEdit to paste a "clut" 
  254.                 resource into the TIFF file you're reading,  this 
  255.                 program will then use that clut to create the Palette, 
  256.                 This is a quick way to give your TIFF pictures a "false" 
  257.                 color representation! */
  258.         color_table = (CTabHandle)Get1IndResource('clut', 1);/* just get the "FIRST" clut to use */
  259.         for(i = 0; i < (**color_table).ctSize; i++)
  260.             (**color_table).ctTable[i].value = i;    /* this is necessary for Color Quick 
  261.                                                         has to know what colors go with 
  262.                                                         what 8 bit values in the TIFF 
  263.                                                         file */
  264.         number_of_pm_entries = (**color_table).ctSize;
  265.         UseResFile(program_resource);
  266.     }
  267. /* now here is where the color palette is created, the palette is used 
  268.     to give the window the colors that are to be used in displaying the 
  269.     TIFF picture.
  270. */ 
  271.         picture_palette = NewPalette(number_of_pm_entries, color_table, 
  272.             pmTolerant, 0x0000);    /* trying changing pmTolerant parameter to 
  273.                                         something else ( see Inside Mac vol 5) 
  274.                                         and see what happens. The 0x0000 tells 
  275.                                         the palette manager to make exact matches 
  276.                                         to display the colors on screen  
  277.                                     */
  278.         if(!picture_palette) /* if i couldn't get enought RAM for the palette, bail out! */
  279.         { 
  280.             SysBeep(10); 
  281.             if(color_table) DisposHandle(color_table);
  282.             if(tiff_map)     DisposHandle(tiff_map);
  283.             if(the_picture) DisposPtr(the_picture);
  284.             if(PicbaseAddr) DisposPtr(PicbaseAddr);
  285.             return (CGrafPtr)0L;
  286.         }
  287.  
  288.         SetEntryColor(picture_palette, 0, &rgb_black);    /* according to Inside Mac Vol 5,
  289.                                                              the first two colors in the 
  290.                                                              palette should be black and  
  291.                                                              white, this tells the 
  292.                                                              palette manager which 
  293.                                                              positions to use for 
  294.                                                              those colors. See page V 158 in Inside Mac */
  295.         SetEntryColor(picture_palette, 1, &rgb_white);
  296.         SetEntryUsage(picture_palette, 0, 0x0000, 0x0000);
  297.         SetEntryUsage(picture_palette, 1, 0x0002, 0x0000);
  298.  
  299.     
  300.         HLock(color_table);
  301.             (**tiff_map).pmTable = color_table;    /* stick our color table into the palette! */
  302.         HUnlock(color_table);
  303.  
  304. /*
  305.     =================================================================================
  306. */
  307.     GetPort(&savedPort);        /* SAVE THE CURRENT P0RT */
  308.     OpenCPort(the_picture);        /* now make our CGrafPort the default port */
  309.     InitCPort(the_picture);        /* initialize our CGrafPort to the default values */
  310.     
  311.     PmForeColor(1);    /* here I tell the Palette Manager which colors to use for the foreground and background drawing */
  312.     PmBackColor(0);
  313.  
  314.     SetPort(the_picture);    /* make my offscreen CGrafPort the default port */
  315.     SetPortPix(tiff_map);    /* now make the PixMap I've created be the CGrafPort's PixMap */
  316.  
  317.     SetPort(savedPort);
  318.  
  319.     window_palette = GetPalette(new_window);    /* if the window already has a palette, then get rid of it */
  320.     if(window_palette)
  321.         DisposePalette(window_palette);
  322.     SetPalette(new_window, picture_palette, TRUE); /* make our palette the window's palette, the TRUE
  323.                                                          parameter tells the Mac that I want update 
  324.                                                          events generated whenever the window's 
  325.                                                          palette changes, for fun try changing it to 
  326.                                                          FALSE  */
  327.     ActivatePalette(new_window);                    /* now turn on the palette */
  328.  
  329.     SetPort(new_window);
  330.         /* 
  331.             now read in the TIFF picture and stick 
  332.             it into the offscreen CGrafPort, the 
  333.             update routine will take care of 
  334.             displaying the image 
  335.         */
  336.     io_errors = SetFPos(file_ref_num, fsFromStart, offset_to_the_image);    /* read in the first IFD */
  337.     io_errors = FSRead(file_ref_num, &picture_size, PicbaseAddr);
  338.     io_errors = FSClose(file_ref_num);
  339.  
  340.     DisposPtr(ifd);            /* clean up after yourself */    
  341.     return the_picture;
  342. }